#include "Function.hpp"
#include "EquationSolver.hpp"
#include <iostream>
#include <cmath>
// Using a different template from problem B
const double Pi = acos(-1.0);  // Define constant for Pi

// Class F6: Represents the function f(x) = sin(x/2) - 1
class F6 : public Function {
public:
    double operator() (double x) const {
        return sin(x / 2) - 1;  // f(x) = sin(x/2) - 1
    }
};

// Class F7: Represents the function f(x) = e^x - tan(x)
class F7 : public Function {
public:
    double operator() (double x) const {
        return exp(x) - tan(x);  // f(x) = e^x - tan(x)
    }
};

// Class F8: Represents the function f(x) = x^3 - 12x^2 + 3x + 1
class F8 : public Function {
public:
    double operator() (double x) const {
        return x * x * x - 12 * x * x + 3 * x + 1;  // f(x) = x^3 - 12x^2 + 3x + 1
    }
};

// Function to solve a given function using Secant Method
void solve_secant_method(const Function& F, double x0, double x1, const std::string& function_name) {
    std::cout << "Solving " << function_name << " using Secant method, starting from x0 = " << x0 << ", x1 = " << x1 << std::endl;
    Secant_Method solver(F, x0, x1);  // Initialize Secant Method solver with the provided function
    double x = solver.solve();  // Solve for the root
    std::cout << "An approximate root is: " << x << std::endl;
}

int main() {
    // Solving f(x) = sin(x/2) - 1
    solve_secant_method(F6(), 0.0, Pi / 2, "sin(x/2) - 1");  // Initial points: x0 = 0.0, x1 = π/2
    solve_secant_method(F6(), 1.0, 4 * Pi , "sin(x/2) - 1");  // Initial points: x0 = 1.0, x1 = 4π
    std::cout << std::endl;
    // Solving f(x) = e^x - tan(x)
    solve_secant_method(F7(), 1.0, 1.4, "e^x - tan(x)");  // Initial points: x0 = 1.0, x1 = 1.4
    solve_secant_method(F7(), 0.0, 3.0, "e^x - tan(x)");  // Initial points: x0 = 0.0, x1 = 3.0
    std::cout << std::endl;
    // Solving f(x) = x^3 - 12x^2 + 3x + 1
    solve_secant_method(F8(), 0.0, -0.5, "x^3 - 12x^2 + 3x + 1");  // Initial points: x0 = 0.0, x1 = -0.5
    solve_secant_method(F8(), 3.0, 5.0, "x^3 - 12x^2 + 3x + 1");  // Initial points: x0 = 3.0, x1 = 5.0
    std::cout << std::endl;
    return 0;
}
